﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TorchView.GameContent.Data;
using TorchView.GameContent.Effects;

namespace TorchView.GameContent.Units
{
    public sealed class Effect : IDataSerializable
    {
        public const string BLOCK_NAME = "EFFECT";

        public Effect()
        {
            Properties = new Dictionary<string, float>(2);

            Name = "";
            Activation = "PASSIVE";
            Duration = "0";
            Type = "";
            DamageType = "";
            Force = -1;
            Resistance = -1;
            Min = -1;
            Max = -1;
            DmgPctMin = -1;
            DmgPctMax = -1;
            Level = 0;
            ParticleFX = "";
            StatModifyName = "";
            StatModifyPercent = "";
            GraphOverride = "";
            NoGraph = false;
            UseOwnerLevel = false;
            UnitTheme = "";
            Save = false;
            Exclusive = false;
            LinkName = "";
        }

        public TorchView.Game.Effect CreateGameEffect()
        {
            TorchView.Game.Effect gameEffect = new TorchView.Game.Effect();

            TorchView.GameContent.Effects.Effect effectRef = EffectList.DefaultList[Type];
            gameEffect.Index = effectRef.Index;
            gameEffect.Name = Name;
            if (Duration.Equals("ALWAYS") || Activation.Equals("PASSIVE"))
                gameEffect.Duration = -1000;
            else if (Duration.Equals("INSTANT"))
                gameEffect.Duration = -900;
            else
            {
                try
                {
                    gameEffect.Duration = int.Parse(Duration);
                }
                catch (Exception e) { }
            }


            if (Activation.Equals("PASSIVE"))
                gameEffect.EffectType = Game.EffectActivationType.Passive;
            else if (Activation.Equals("TRANSFER"))
                gameEffect.EffectType = Game.EffectActivationType.Target;
            else if (Activation.Equals("DYNAMIC"))
                gameEffect.EffectType = Game.EffectActivationType.Use;

            switch (DamageType)
            {
                case "ALL":
                    gameEffect.DamageType = Game.DamageSourceType.AllTypes;
                    break;
                case "FIRE":
                    gameEffect.DamageType = Game.DamageSourceType.Fire;
                    break;
                case "ICE":
                    gameEffect.DamageType = Game.DamageSourceType.Ice;
                    break;
                case "ELECTRIC":
                    gameEffect.DamageType = Game.DamageSourceType.Electric;
                    break;
                case "POISON":
                    gameEffect.DamageType = Game.DamageSourceType.Poison;
                    break;
                case "PHYSICAL":
                    gameEffect.DamageType = Game.DamageSourceType.Physical;
                    break;
            }

            if (effectRef.Value1.Equals("FORCE"))
            {
                gameEffect.Bonus = Force;
            }
            else if (effectRef.Value1.Equals("RESISTANCE"))
            {
                gameEffect.Bonus = Resistance;
            }
            else if (effectRef.Value1.Equals("MIN"))
            {
                gameEffect.RangeMin = Min;
                gameEffect.RangeMax = Max;
                gameEffect.Bonus = Max;
            }

            if (effectRef.Value3.Equals("DMGPCTMIN"))
            {
                gameEffect.PctMin = DmgPctMin;
                gameEffect.PctMax = DmgPctMax;
            }

            return gameEffect;
        }

        #region IDataSerializable Members

        public DataBlock MakeDataBlock()
        {
            var block = Data == null ? new DataBlock(BLOCK_NAME) : Data;

            block.SetOrClearPropertyValue(Name != "", "NAME", Name);
            block.SetOrClearPropertyValue(Activation != "", "ACTIVATION", Activation);
            block.SetOrClearPropertyValue(Duration != "", "DURATION", Duration);
            block.SetOrClearPropertyValue(Level != 0, "LEVEL", Level);
            block.SetOrClearPropertyValue(Type != "", "TYPE", Type);
            block.SetOrClearPropertyValue(DamageType != "", "DAMAGE_TYPE", DamageType);
            block.SetOrClearPropertyValue(ParticleFX != "", "PARTICLE_FX", ParticleFX);
            block.SetOrClearPropertyValue(StatModifyName != "", "STATMODIFYNAME", StatModifyName);
            block.SetOrClearPropertyValue(StatModifyPercent != "", "STATMODIFYPERCENT", StatModifyPercent);
            block.SetOrClearPropertyValue(GraphOverride != "", "GRAPHOVERRIDE", GraphOverride);
            block.SetOrClearPropertyValue(NoGraph, "NOGRAPH", NoGraph);
            block.SetOrClearPropertyValue(UseOwnerLevel, "USEOWNERLEVEL", UseOwnerLevel);
            block.SetOrClearPropertyValue(UnitTheme != "", "UNITTHEME", UnitTheme);
            block.SetOrClearPropertyValue(Save, "SAVE", Save);
            block.SetOrClearPropertyValue(Exclusive, "EXCLUSIVE", Exclusive);
            block.SetOrClearPropertyValue(LinkName != "", "LINK_NAME", LinkName);

            foreach (var property in Properties)
                block.SetPropertyValue(property.Key, property.Value);

            return block;
        }

        public void LoadFromDataBlock(DataBlock block)
        {
            if (block == null)
                throw new ArgumentNullException("block");
            if (block.Name != BLOCK_NAME)
                throw new ArgumentException("Incorrect block type, only " + BLOCK_NAME + " is supported.");

            Data = block;

            Name = block.GetPropertyValue("NAME", Name);
            Activation = block.GetPropertyValue("ACTIVATION", Activation);
            Duration = block.GetPropertyValue("DURATION", Duration);
            Type = block.GetPropertyValue("TYPE", Type);
            DamageType = block.GetPropertyValue("DAMAGE_TYPE", DamageType);
            Force = block.GetPropertyValue("FORCE", Force);
            Resistance = block.GetPropertyValue("RESISTANCE", Resistance);
            Min = block.GetPropertyValue("MIN", Min);
            Max = block.GetPropertyValue("MAX", Max);
            DmgPctMin = block.GetPropertyValue("DMGPCTMIN", DmgPctMin);
            DmgPctMax = block.GetPropertyValue("DMGPCTMAX", DmgPctMax);
            Level = block.GetPropertyValue("LEVEL", 0);
            ParticleFX = block.GetPropertyValue("PARTICLE_FX", "");
            StatModifyName = block.GetPropertyValue("STATMODIFYNAME", "");
            StatModifyPercent = block.GetPropertyValue("STATMODIFYPERCENT", "");
            GraphOverride = block.GetPropertyValue("GRAPHOVERRIDE", "");
            NoGraph = block.GetPropertyValue("NOGRAPH", false);
            UseOwnerLevel = block.GetPropertyValue("USEOWNERLEVEL", false);
            UnitTheme = block.GetPropertyValue("UNITTHEME", "");
            Save = block.GetPropertyValue("SAVE", false);
            Exclusive = block.GetPropertyValue("EXCLUSIVE", false);
            LinkName = block.GetPropertyValue("LINK_NAME", "");

            // To Do: Add extended properties
        }

        #endregion

        public DataBlock Data { get; set; }
        public Dictionary<string, float> Properties { get; private set; }
        public string Type { get; set; }
        public string Name { get; set; }
        public string Activation { get; set; }
        public string Duration { get; set; }
        public int Level { get; set; }
        public string DamageType { get; set; }
        public string GraphOverride { get; set; }
        public string StatModifyPercent { get; set; }
        public string StatModifyName { get; set; }
        public string ParticleFX { get; set; }
        public bool NoGraph { get; set; }
        public bool UseOwnerLevel { get; set; }
        public string UnitTheme { get; set; }
        public bool Save { get; set; }
        public bool Exclusive { get; set; }
        public string LinkName { get; set; }
        public float Force { get; set; }
        public float Resistance { get; set; }
        public float Min { get; set; }
        public float Max { get; set; }
        public float DmgPctMin { get; set; }
        public float DmgPctMax { get; set; }
    }
}
